package com.seven.tools.ssh;

import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.StrUtil;
import com.jcraft.jsch.*;
import lombok.NonNull;
import lombok.extern.log4j.Log4j2;

import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

@Log4j2
public class SshObject {

    private Session session;

    public SshObject(Machine machine) {
        //建立ssh连接
        JSch jSch = new JSch();
        //设置JSch 的日志，可以看到具体日志信息
        JSch.setLogger(new Logger() {
            @Override
            public boolean isEnabled(int level) {
                return true;
            }

            @Override
            public void log(int level, String message) {
                System.out.println("logger:" + message);
            }
        });
        try {
            session = jSch.getSession(machine.getUsername(), machine.getIp());
            session.setPassword(machine.getPassword());
            //忽略第一次连接时候 hostkey 检查
            session.setConfig("StrictHostKeyChecking", "no");
            //设置首选的身份验证方式
            session.setConfig("PreferredAuthentications", "publickey,keyboard-interactive,password");
            synchronized (SshObject.class) {
                session.connect(10000);
            }
            if (session.isConnected()) {
                log.info("连接成功");
            }
        } catch (JSchException e) {
            e.printStackTrace();
        }
    }

    /**
     * 上传文件
     */
    public boolean uploadBySftp(String dst, @NonNull List<String> srcList) {
        //建立sftp
        ChannelSftp sftp = null;
        try {
            sftp = (ChannelSftp) session.openChannel("sftp");
        } catch (JSchException e) {
            e.printStackTrace();
            return false;
        }
        try {
            sftp.connect(10000);
            if (dst == null) dst = sftp.getHome();
            String finalDst = dst;
            ChannelSftp finalSftp = sftp;
            srcList.forEach(s -> {
                try {
                    finalSftp.put(s, finalDst);
                } catch (SftpException e) {
                    log.error(String.format("上传文件%s失败,错误原因:%s", s, e.getMessage()));
                }
            });
            return true;
        } catch (JSchException | SftpException e) {
            e.printStackTrace();
        }
        return false;
    }

    public boolean uploadBySftp(String dst, @NonNull String src) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add(src);
        return uploadBySftp(dst, arrayList);
    }

    public boolean uploadBySftp(String dst, String... srcList) {
        List<String> strings = Arrays.asList(srcList);
        return uploadBySftp(dst, strings);
    }

    public boolean upload2Home(@NonNull List<String> srcList) {
        return uploadBySftp(null, srcList);
    }

    public boolean upload2Home(@NonNull String src) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add(src);
        return uploadBySftp(null, arrayList);
    }

    public boolean upload2Home(String... srcList) {
        List<String> strings = Arrays.asList(srcList);
        return upload2Home(strings);
    }


    /**
     * 在home中删除文件
     */
    public boolean removeInHome(String path) {
        ChannelSftp sftp = null;
        try {
            sftp = (ChannelSftp) session.openChannel("sftp");
        } catch (JSchException e) {
            e.printStackTrace();
            return false;
        }
        try {
            sftp.connect(10000);
            log.debug("删除" + sftp.getHome() + "/" + path);
            sftp.rm(sftp.getHome() + "/" + path);
            return true;
        } catch (SftpException | JSchException e) {
            e.printStackTrace();
        }
        return false;
    }

    /**
     * 执行命令
     */
    public String exec(String command) {
        ChannelExec exec = null;
        try {
            exec = (ChannelExec) session.openChannel("exec");
        } catch (JSchException e) {
            e.printStackTrace();
            return null;
        }
        InputStream errStream = null;
        InputStream inputStream = null;
        try {
            exec.setCommand(command);
            exec.connect(10000);
            errStream = exec.getErrStream();
            inputStream = exec.getInputStream();
            String read = IoUtil.read(inputStream, "UTF-8");
            log.debug("执行结果：\n" + read);
            String errorInfo = IoUtil.read(errStream, "UTF-8");
            if (!StrUtil.isEmpty(errorInfo)) {
                log.warn("执行命令失败：" + errorInfo);
            }
            return read;
        } catch (IOException | JSchException e) {
            e.printStackTrace();
        } finally {
            try {
                if (errStream != null) errStream.close();
                if (inputStream != null) inputStream.close();
                exec.disconnect();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return null;
    }


    /**
     * 关闭连接
     */
    public void closeSession() {
        if (session != null) session.disconnect();
    }

}
